<template>
  <div>
     <!-- 面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>权限管理</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片 -->
    <el-card>
      <!-- 添加按钮 -->
      <el-row>
        <el-col>
          <el-button type="primary" @click="addFormRoleVisible = true">添加用户</el-button>
        </el-col>
      </el-row>
      <!-- 给表格绑定数据 :data -->
      <el-table :data="rolesList" stripe border>
        <!-- 展开列 -->
        <el-table-column type="expand">
          <!-- 使用作用域插槽渲染权限 -->
          <template slot-scope="scope">
            <!-- 这里使用了element-ui栅格化 -->
            <el-row :class="['border-bottom' , index === 0 ? 'border-top': '','vcenter']" v-for="(item1, index) in scope.row.children" :key="item1.id">
              <!-- 渲染一级权限 占5个单位 一共24个单位-->
              <el-col :span="5" >
                <el-tag type="primary" closable @close="removeRightById(scope.row,item1.id)">{{item1.authName}}</el-tag>
                <!-- 小箭头 -->
                <i class="el-icon-caret-right"></i>
              </el-col>
              <!-- 渲染二级权限 占19个单位 一共24个单位-->
              <el-col :span="19">
                <!-- 二级权限分 左右 左边是二级  右边是三级 -->
                <el-row :class="[index2 === 0 ? '': 'border-top','vcenter']" :gutter="20" v-for="(item2,index2) in item1.children" :key="item2.id">
                  <!-- 左边二级 -->
                  <el-col :span="6">
                    <el-tag  type="success" closable @close="removeRightById(scope.row,item2.id)">{{item2.authName}}</el-tag>
                    <!-- 小箭头 -->
                    <i class="el-icon-caret-right"></i>
                  </el-col>
                  <!-- 右边三级 -->
                  <el-col :span="18">
                    <el-tag class="eltag3" closable @close="removeRightById(scope.row,item3.id)" v-for="(item3,index3) in item2.children" :key="index3" type="warning">{{item3.authName}}</el-tag>
                  </el-col>
                </el-row>
              </el-col>
            </el-row>
          </template>
        </el-table-column>
        <!-- 添加索引 -->
        <el-table-column type="index" label="#"></el-table-column>
        <el-table-column prop="roleName" label="角色名称"></el-table-column>
        <el-table-column prop="roleDesc" label="角色描述"></el-table-column>
        <el-table-column label="操作">
          <template slot-scope="scope">
            <el-button size="mini" type="primary"  @click="getRoleInfo(scope.row)" icon="el-icon-edit">修改</el-button>
            <el-button size="mini" type="danger" @click="removeDialog(scope.row)" icon="el-icon-delete">删除</el-button>
            <el-button size="mini" type="warning" @click="setRight(scope.row)" icon="el-icon-setting">分配权限</el-button>
          </template>
        </el-table-column>
      </el-table>
    <!-- 分配权限对话框 -->
    <el-dialog
      title="分配权限"
      :visible.sync="setRightVisible"
      @close="clearRightData"
      width="70%">
      <!-- Tree控件绑定数据rightList Tree控件对象是treeList里面指定了所要展示的 数据的哪些字段 -->
      <!-- node-key在这里绑定了 id 其实就是 TreeList指定的chilren中的id -->
      <!-- default-expend-all 默认展开所有项 -->
      <!-- show-checkbox 为每个树节点添加一个复选框 -->
      <!-- default-checked-keys	默认勾选的节点的 key 的数组 -->
      <el-tree ref="rightRef" :default-checked-keys="deaKeys" :data="rightList" :props="treeList" node-key="id" show-checkbox default-expand-all></el-tree>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setRightVisible = false">取 消</el-button>
        <el-button type="primary" @click="setAllRight">确 定</el-button>
      </span>
    </el-dialog>
     <!-- 修改用户的对话框 -->
    <el-dialog
      @close="editRoleClear"
      title="修改用户"
      :visible.sync="editRoleVisible"
      width="50%">
      <!-- 修改用户表单 -->
      <el-form :model="editForm"  ref="editFormRef" label-width="100px">
        <el-form-item label="角色名称" >
          <el-input v-model="editForm.roleName"></el-input>
        </el-form-item>
        <el-form-item label="角色描述" >
          <el-input v-model="editForm.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="editRoleVisible = false">取 消</el-button>
        <el-button type="primary" @click="editRole(editForm.id)">确 定</el-button>
      </span>
    </el-dialog>
     <!-- 添加用户的对话框 -->
    <el-dialog
      @close="addRoleClear"
      title="修改用户"
      :visible.sync="addFormRoleVisible"
      width="50%">
      <!-- 添加用户表单 -->
      <el-form :model="addForm" :rules="addFormRules"  ref="addFormRef" label-width="100px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="addForm.roleName"></el-input>
        </el-form-item>
        <el-form-item label="角色描述" prop="roleDesc">
          <el-input v-model="addForm.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addFormRoleVisible = false">取 消</el-button>
        <el-button type="primary" @click="addRoleForm()">确 定</el-button>
      </span>
    </el-dialog>
    </el-card>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      // 权限用户列表
      rolesList: [],
      // 分配权限dialog的显示和隐藏
      setRightVisible: false,
      // 权限列表
      rightList: [],
      // 树形控件绑定的对象  因为Tree组件data绑定了 权限列表rightList
      // 所以在里面要指定 相应的字段
      treeList: {
        // 名字
        label: 'authName',
        // 绑定的子对象
        children: 'children'
      },
      // 默认勾选的节点 的ID数组
      deaKeys: [],
      // 保存下当前搜分配权限的ID
      currentID: 0,
      // 修改角色的信息
      editForm: {},
      // 修改角色对话框
      editRoleVisible: false,
      // 添加角色对话框
      addFormRoleVisible: false,
      // 添加角色的信息
      addForm: {
        roleName: '',
        roleDesc: ''
      }, addFormRules: {
        roleName: [
          { required: true, message: '请输入角色名', trigger: 'blur' },
          { min: 2, max: 25, message: '长度在 2 到 25 个字符', trigger: 'blur' }
        ], roleDesc: [
          { required: true, message: '请输入描述', trigger: 'blur' },
          { min: 1, max: 110, message: '长度 110 个字符以内', trigger: 'blur' }
        ]
      }
    }
  },
  created() {
    // 获取权限用户列表
    this.getRolesList()
  },
  methods: {
    // 获取权限用户列表方法
    async getRolesList() {
      const { data: res } = await this.$http.get('/roles')
      // 判断是否成功
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      // 成功就赋值给 rolesList
      this.rolesList = res.data
      // console.log(this.rolesList)
    },
    // 删除权限
    async removeRightById(role, id) {
      // role是传过来的 每一个角色 ,id 是当前所要删除权限的id
      // 该对话框 返回的一个字符串 promise对象
      const resStr = await this.$confirm('此操作将永久删除该权限, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)
      // 判断是否确定删除
      if (resStr !== 'confirm') return this.$message.info('用户取消操作')
      const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${id}`)
      // 修改失败就阻止
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      this.$message.success(res.meta.msg)
      // 重新查询数据 不建议这样做 不然会重新渲染页面会关闭
      // this.getRolesList()
      // 因为接口中 delete后面是直接返回的最新的数据
      // 所以通过重新赋值可以得到新的数据
      role.children = res.data
    },
    // 分配权限获取
    async setRight(row) {
      // 把当前的ID给 this.中的当前的id
      this.currentID = row.id
      // 显示分配权限对话框
      this.setRightVisible = true
      // 根据查询所有的权限
      const { data: res } = await this.$http.get('/rights/tree')
      // 验证结果
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      // 把所有的权限都赋值给 权限列表
      this.rightList = res.data
      // 通过递归获取所有的三级ID
      this.getKeys(row, this.deaKeys)
      // console.log(this.deaKeys)
    },
    // 通过递归实现获取3级节点 所有选中权限的ID
    getKeys(item, arr) {
      // 如果是3级节点就把id添加进去
      if (!item.children) {
        return arr.push(item.id)
      }
      // 不是三级节点的话就继续找儿子
      item.children.forEach(item => this.getKeys(item, arr))
    },
    // 分配权限对话框关闭之后就清空保存节点ID的数组
    clearRightData() {
      // 清空数组
      this.deaKeys = []
    },
    // 分配权限
    async setAllRight() {
      // 获取到Tree组件上面的所有的 选中 和 半选中的ID
      // getCheckedKeys	若节点可被选择（即 show-checkbox 为 true），则返回目前被选中的节点的 key 所组成的数组
      // getHalfCheckedKeys	若节点可被选择（即 show-checkbox 为 true），则返回目前半选中的节点的 key 所组成的数组
      // 把ID们通过‘,’ 变成 字符串数组
      const checkedID = [
        ...this.$refs.rightRef.getCheckedKeys(),
        ...this.$refs.rightRef.getHalfCheckedKeys()
      ].join(',')
      // 修改
      const { data: res } = await this.$http.post(`roles/${this.currentID}/rights`, { rids: checkedID })
      // 进行判断
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      this.$message.success(res.meta.msg)
      // 隐藏对话框
      this.setRightVisible = false
      // 重新查询数据
      this.getRolesList()
    },
    // 添加角色
    addRoleForm() {
      this.$refs.addFormRef.validate(async vaild => {
        if (!vaild) return false
        const { data: res } = await this.$http.post('/roles', this.addForm)
        // 更新失败就阻止
        if (res.meta.status !== 201) return this.$message.error(res.meta.msg)
        this.$message.success(res.meta.msg)
        // 关闭编辑页面
        this.addFormRoleVisible = false
        // 重新查询数据
        this.getRolesList()
      })
    },
    // 取消添加
    addRoleClear() {
      this.addForm = {}
      this.addFormRoleVisible = false
    },
    // 获取修改角色信息
    getRoleInfo(item) {
      this.editForm = item
      this.editRoleVisible = true
    },
    // 确认修改角色信息
    async editRole() {
      this.$refs.editFormRef.validate(async vaild => {
        if (!vaild) return false
        const { data: res } = await this.$http.put('/roles/' + this.editForm.id, this.editForm)
        // 更新失败就阻止
        if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
        this.$message.success(res.meta.msg)
        // 关闭编辑页面
        this.editRoleVisible = false
        // 重新查询数据
        this.getRolesList()
      })
    },
    // 取消修改
    editRoleClear() {
      this.editForm = {}
      this.editRoleVisible = false
    },
    // 删除角色
    async removeDialog(item) {
      // 该对话框 返回的一个字符串 promise对象
      const resStr = await this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)
      // 判断是否确定删除
      if (resStr !== 'confirm') return this.$message.info('用户取消操作')
      const { data: res } = await this.$http.delete('/roles/' + item.id)
      // 修改失败就阻止
      if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
      this.$message.success(res.meta.msg)
      // 重新查询数据
      this.getRolesList()
    }
  }
}
</script>

<style lang="less" scoped>
.el-tag{
  margin: 8px 0;
}
.border-top{
  border-top: 1px dashed skyblue;
}
.border-bottom{
  border-bottom: 1px dashed skyblue;
}
.eltag3{
  margin-left: 15px;
}

// 垂直居中的类
.vcenter {
  display: flex;
  align-items: center;
}
</style>
